package com.fiveGroup.ceptor;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fiveGroup.pojo.AdminUser;
import com.fiveGroup.pojo.User;
import com.fiveGroup.pojo.vo.DataVo;
import com.fiveGroup.service.AdminUserService;
import com.fiveGroup.service.UserService;
import com.fiveGroup.util.JwtUtil;
import com.fiveGroup.util.UserContextHolder;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import java.io.IOException;
import java.nio.charset.StandardCharsets;

/**
 * ClassName: AuthInterceptor
 * Package:
 * Description
 * <p>
 * 鉴权拦截器
 * 用于系统前置鉴权
 * <p>
 * ctrl+alt+m
 *
 * @Author wen
 * @Create 2025/9/17 15:20
 * @Version 1.0
 */
@Slf4j
@RequiredArgsConstructor
@Component
public class AuthInterceptor implements HandlerInterceptor {

    private final JwtUtil jwtUtil;
    private final ObjectMapper objectMapper;

    private final UserService userService;

    //添加管理员方便判断
    private final AdminUserService adminUserService;

    //请求前置处理器
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 对OPTIONS请求直接放行
        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
            return true;
        }
        //1.获取请求头中的token
        String token = request.getHeader("token");
        // Token校验流程：
        // 1. 检查token是否有效
        // 2. 验证用户状态
        try {
            try {
                if (token != null) {
                    //isTokenExpired令牌是否已过期
                    Boolean tokenExpired = jwtUtil.isTokenExpired(token);
                    if (tokenExpired) {
                        // token过期，返回401未授权
                        error(response, 401, "请登录");
                        return false;
                    }
                    //判断封禁信息
                    // 解析token获取claims
                    Claims claims = jwtUtil.extractAllClaims(token);
                    // 从claims中获取用户ID
                    Integer userId = (Integer) claims.get("userId");
                    if (userId == null) {
                        // 用户ID不存在，返回401未授权
                        error(response, 401, "请登录");
                        return false;
                    } else {
                        //获取登录的类型（用户 或者 管理员） user / admin
                        String userType = (String) claims.get("userType");
                        if (userType == null) {
                            error(response, 401, "无效的登录信息");
                            return false;
                        }

                        //管理员
                        if ("admin".equals(userType)) {
                            // 如果是管理员，使用 AdminUserService 去查询
                            AdminUser adminUser = adminUserService.getById(userId);
                            if (adminUser == null) {
                                error(response, 500, "管理员不存在");
                                return false;
                            }
                            if (adminUser.getStatus() != null && adminUser.getStatus().equals(0)) {
                                // 管理员被封禁，返回403禁止访问
                                error(response, 403, "管理员被封禁");
                                return false;
                            }
                            //构造一个新的user对象
                            User user = new User();
                            user.setUsername(adminUser.getUsername());
                            user.setPassword(adminUser.getPassword());
                            user.setStatus(1);
                            //校验成功 设置全局上下文 存储管理员信息
                            UserContextHolder.setUser(user);
                        } else if ("user".equals(userType)) {
                            //用户
                            User userByDb = userService.getById(userId);
                            if (userByDb == null) {
                                error(response, 500, "用户不存在");
                                return false;
                            }
                            if (userByDb.getStatus().equals(1)) {
                                error(response, 403, "用户已被封禁");
                                return false;
                            }
                            //校验成功 设置全局上下文 存储用户信息
                            UserContextHolder.setUser(userByDb);
                        }else {
                            error(response, 401, "未知的用户类型");
                            return false;
                        }
                    }
                    return true;
                } else {
                    // 请求头中没有token，返回401未授权
                    error(response, 401, "鉴权失败");
                    return false;
                }
            } catch (ExpiredJwtException e) {
                error(response, 401, "凭证过期,请重新登录");
                return false;
            }
        } catch (Exception e) {
            // 捕获并打印异常，返回false拒绝访问
            e.printStackTrace();
            error(response, 401, "鉴权失败");
            return false;
        }
    }

    private void error(HttpServletResponse response, Integer code, String msg) throws IOException {
        DataVo<Object> dataVo = new DataVo<>();
        dataVo.setCode(code);
        dataVo.setMsg(msg);
        //设置响应体的字符编码为UTF-8
        response.setCharacterEncoding(StandardCharsets.UTF_8.toString());
        //响应HTTP状态码 401 未授权
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.getWriter().write(
                objectMapper.writeValueAsString(dataVo)
        );
    }

    /**
     * 请求后置处理器
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        //清除当前线程的用户上下文 防止内存泄露
        UserContextHolder.clear();
    }
}
